package com.dmz.auth.granter;

import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.StringUtils;

import com.dmz.auth.exception.NullArgumentException;
import com.dmz.auth.model.AuthUserDetails;
import com.dmz.auth.service.UserInfoService;
/**
 * 自定义手机模式的提供者
 * 判断token类型是否为PhoneAndPasswordAuthenticationToken,如果是则会使用此provider
 */

public class PhoneAndPasswordAuthenticationProvider implements AuthenticationProvider, MessageSourceAware {

    private MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
    @Override
    public void setMessageSource(MessageSource messageSource) {
        this.messages = new MessageSourceAccessor(messageSource);
    }

    /**
     * userDetailsService的实现类 不需要自动注入 直接传入
     */
    private UserDetailsService userInfoService;


    /**
     * 业务处理的方法
     * @param authentication
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        //未认证之前是手机号 认证之后是客户信息
        String principal =(String) authentication.getPrincipal();
        if (StringUtils.isEmpty(principal)){
            throw  new BadCredentialsException("手机号不能为空");
        }
        // 这里的Credentials是先通过AbstractTokenGranter组装  new MobileCodeAuthenticationToken()传入的
        String code = (String) authentication.getCredentials();
        if (code == null) {
            throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "手机验证码不能为空"));
        }
        //正式环境放开注释

//        String key=AuthConstant.AUTH_SMS_CACHE_KEY+principal+code;
//        Object cacheCode = redisTemplate.opsForValue().get(key);
//        if (cacheCode == null || !cacheCode.toString().equals(code)) {
//            throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "验证码无效"));
//        }
        //清除redis中的短信验证码
        //stringRedisTemplate.delete(RedisConstant.SMS_CODE_PREFIX + mobile);
        AuthUserDetails user;
        try {
            user = (AuthUserDetails)userInfoService.loadUserByUsername(principal);
        } catch (UsernameNotFoundException var6) {
           throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "查询用户信息失败!"));
        }
        check(user);
        PhoneAndPasswordAuthenticationToken authenticationToken = new PhoneAndPasswordAuthenticationToken(user, code, user.getAuthorities());
        authenticationToken.setDetails(authenticationToken.getDetails());
        return authenticationToken;
    }

    /**
     * 账号禁用、锁定、超时校验
     *
     * @param user
     */
    private void check(UserDetails user) {
        if (user==null){
            throw  new NullArgumentException(this.messages.getMessage( "未查询到用户"));
        }
        if (!user.isAccountNonLocked()) {
            throw new LockedException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked", "User account is locked"));
        } else if (!user.isEnabled()) {
            throw new DisabledException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled", "User is disabled"));
        } else if (!user.isAccountNonExpired()) {
            throw new AccountExpiredException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired", "User account has expired"));
        }
    }

    /**
     * 判断是否为MobileCodeAuthenticationToken类型  如果是 直接调用 切断过滤器链
     * 如果不是 继续查找
     * @param authentication
     * @return
     */
    @Override
    public boolean supports(Class<?> authentication) {
        return PhoneAndPasswordAuthenticationToken.class.isAssignableFrom(authentication);
    }

	public UserDetailsService getUserInfoService() {
		return userInfoService;
	}

	public void setUserInfoService(UserDetailsService userInfoService) {
		this.userInfoService = userInfoService;
	}
}